﻿using System;
using System.Net;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;

namespace NASA.BeAMartian.Utils
{
    public static class EnumUtils
    {
        public static T[] GetEnumValues<T>()
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            return (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral
              select (T)field.GetValue(type)).ToArray();
        }

        public static string[] GetEnumStrings<T>()
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            return (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral
              select field.Name).ToArray();
        }

        public static EnumDatum<T>[] GetEnumData<T>(Func<T,string> converter, T [] ignoreList)
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            EnumDatum<T>[] ret = (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral && ignoreList == null || (ignoreList.Contains((T)field.GetValue(type)) == false)
              orderby field.Name
              select new EnumDatum<T>()
              {
                  Value = (T)field.GetValue(type),
                  Name = (converter == null ? field.Name : converter((T)field.GetValue(type)))
              }).ToArray();

            return ret;
        }

        public static EnumDatum<T>[] GetEnumData<T>()
        {
            return EnumUtils.GetEnumData<T>(null, null);
        }

        public static EnumDatum<T> GetItem<T>(IEnumerable<EnumDatum<T>> values, T value)
        {
            var val = from ret in values where value.Equals(ret.Value) select ret;
            return val.FirstOrDefault();
        }

        public static EnumDatum<T> GetEnumDatum<T>(Func<T, string> converter, T item)
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException("Type '" + type.Name + "' is not an enum");

            return (
              from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
              where field.IsLiteral && (item.Equals((T)field.GetValue(type)))
              select new EnumDatum<T>()
              {
                  Value = (T)field.GetValue(type),
                  Name = (converter == null ? field.Name : converter((T)field.GetValue(type)))
              }).FirstOrDefault();
        }
    }
}